package n19_double_check_locking问题;

import n18_犹豫模式_在n17基础上优化.T2_Singleton;

/*--------------------------------------------------------------------
|                                                                    |
|       -----------     双检查 锁模式 单例      -------------          |
|                                                                    |
|====================================================================*/
public class T1_单例1 {
    private T1_单例1() {}

    private static T1_单例1 INSTANCE = null;
    // 懒惰初始化 饿汉式单例 ； 不为空 才创建
    public static synchronized T1_单例1 getInstance() {
        if (INSTANCE != null) {
            return INSTANCE;
        }
        INSTANCE = new T1_单例1();
        return INSTANCE;
    }
}
/*---------------------------------------------------
|                                                   |
|          这里性能低，每次获取对象都要进入锁            |
|                                                   |
|==================================================*/
class Singleton1 {
    private Singleton1() {}

    private static volatile Singleton1 INSTANCE = null;

    public static synchronized  Singleton1 getInstance() {

        if (INSTANCE == null) {

            INSTANCE = new Singleton1();
        }
        return INSTANCE;

    }
}

/**
 * 改造： 使用 synchronized 锁
 *
 * 这里会 有 产生 半成品对象的问题
 * 原因是 INSTANCE = new Singleton2(); 构造方法的执行 和 赋值的指令 会产生重排序！
 * 1. 同步代码块 只能保证原子性 和 可见性 ；但是不能保证 [-有序性-]
 * 2.
 */
class Singleton2 {

    private Singleton2() {}

    private static volatile Singleton2 INSTANCE = null;

    // 懒惰初始化 饿汉式单例 ； 不为空 才创建
    public static  Singleton2 getInstance() {

        if (INSTANCE == null) {                  // t2   这里可能拿到new的对象但是构造方法还未执行完 (半成品对象)

            synchronized (Singleton2.class) {
                if (INSTANCE == null) {          // t1
                    /**
                     * 也许 jvm 会优化为：先执行 [--- 利用一个对象引用，赋值给 static INSTANCE ---]，
                     *                  再执行 [--- 利用一个对象引用，调用构造方法 ---]。
                     */
                    INSTANCE = new Singleton2();
                }
            }
        }
        return INSTANCE;

    }
}

